package com.taocore.top.title.service;

import java.sql.Connection;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang.StringUtils;

import com.taobao.api.ApiException;
import com.taobao.api.DefaultTaobaoClient;
import com.taobao.api.TaobaoClient;
import com.taobao.api.TaobaoResponse;
import com.taobao.api.domain.ArticleUserSubscribe;
import com.taobao.api.domain.Item;
import com.taobao.api.domain.ItemCat;
import com.taobao.api.domain.User;
import com.taobao.api.request.ItemGetRequest;
import com.taobao.api.request.ItemUpdateRequest;
import com.taobao.api.request.ItemcatsGetRequest;
import com.taobao.api.request.ItempropsGetRequest;
import com.taobao.api.request.ItemsGetRequest;
import com.taobao.api.request.ItemsInventoryGetRequest;
import com.taobao.api.request.ItemsListGetRequest;
import com.taobao.api.request.ItemsOnsaleGetRequest;
import com.taobao.api.request.KfcKeywordSearchRequest;
import com.taobao.api.request.ProductGetRequest;
import com.taobao.api.request.SellercatsListGetRequest;
import com.taobao.api.request.UserGetRequest;
import com.taobao.api.request.VasSubscribeGetRequest;
import com.taobao.api.response.ItemGetResponse;
import com.taobao.api.response.ItemUpdateResponse;
import com.taobao.api.response.ItemcatsGetResponse;
import com.taobao.api.response.ItempropsGetResponse;
import com.taobao.api.response.ItemsGetResponse;
import com.taobao.api.response.ItemsInventoryGetResponse;
import com.taobao.api.response.ItemsListGetResponse;
import com.taobao.api.response.ItemsOnsaleGetResponse;
import com.taobao.api.response.KfcKeywordSearchResponse;
import com.taobao.api.response.ProductGetResponse;
import com.taobao.api.response.SellercatsListGetResponse;
import com.taobao.api.response.UserGetResponse;
import com.taobao.api.response.VasSubscribeGetResponse;
import com.taocore.top.title.Constants;
import com.taocore.top.title.db.DBUtils;
import com.taocore.top.title.db.Dao;
import com.taocore.top.title.domain.RealTimeKeyword;
import com.taocore.top.title.domain.WeeklyKeyword;
import com.taocore.utils.PagingResult;

public class TaobaoService implements Constants{
	
	static Logger _log = Logger.getLogger(TaobaoService.class.getName());
	
	public static final long PAGE_SIZE = 200;	
	
	private static String getApiUrl()
	{
		return "http://gw.api.taobao.com/router/rest";
	}
	
	private static String getAppKey()
	{
		return APP_KEY;
	}
	
	private static String getAppSecret()
	{
		return SECRET;
	}
	
	public static TaobaoClient createClient()
	{
		return new DefaultTaobaoClient(getApiUrl(), getAppKey(), getAppSecret());
	}
	
	public static User getUser(String session) throws ApiException
	{
		UserGetRequest req = new UserGetRequest();
		req.setFields("user_id,uid,nick");
		//req.setNick(nick);
		UserGetResponse rsp = createClient().execute(req, session);
		return rsp.getUser();
	}
	
	public static ItemGetResponse getItem(long numIid, String fields, String session) throws ApiException
	{
		ItemGetRequest req = new ItemGetRequest();
		req.setFields(fields);
		req.setNumIid(numIid);
		return createClient().execute(req, session);
	}
	
	public static ItemsOnsaleGetResponse getOnSales(String fields, String keyWord, String sellerCids, String order, long pageNumber, long pageSize, String session) throws ApiException
	{
		ItemsOnsaleGetRequest req = new ItemsOnsaleGetRequest();
		if (fields != null)
		{
			req.setFields(fields);
		}
		else
		{
			req.setFields("num_iid,title,pic_url,price,list_time,delist_time,has_showcase");
		}
		if (keyWord != null)
		{
			req.setQ(keyWord);
		}
		if (sellerCids != null)
		{
			req.setSellerCids(sellerCids);
		}
		if (order != null)
		{
			req.setOrderBy(order);
		}
		req.setPageNo(pageNumber);
		req.setPageSize(pageSize);
		return createClient().execute(req, session);
	}
	
	public static ItemsInventoryGetResponse getInventory(String fields, String keyword, String sellerCids, String banner, String order, long pageNumber, long pageSize, String session) throws ApiException
	{
		ItemsInventoryGetRequest req = new ItemsInventoryGetRequest();
		if (fields != null)
		{
			req.setFields(fields);
		}
		else
		{
			req.setFields("num_iid,title,pic_url,price,num,list_time,delist_time,nick,has_showcase");
		}
		if (keyword != null)
		{
			req.setQ(keyword);
		}
		if (sellerCids != null)
		{
			req.setSellerCids(sellerCids);
		}
		if (banner != null)
		{
			req.setBanner(banner);
		}
		if (order != null)
		{
			req.setOrderBy(order);
		}
		req.setPageNo(pageNumber);
		req.setPageSize(pageSize);
		return createClient().execute(req, session);
	}
	
	public static ItemsListGetResponse getItems(String numIids, String fields, String session) throws ApiException
	{
		ItemsListGetRequest req = new ItemsListGetRequest();
		req.setFields(fields);
		req.setNumIids(numIids);
		return createClient().execute(req, session);
	}
	
	public List<Item> getAllItems(String numIids, String fields, String session) throws Exception
	{
		_log.info("numIids: " + numIids);
		List<Item> items = new ArrayList<Item>();
		if (numIids != null && numIids.length() > 0)
		{
			String[] numIidArray = numIids.split(",");
			if (numIidArray != null && numIidArray.length > 0)
			{
				_log.info("length: " + numIidArray.length);
				int pages = numIidArray.length / 20;
				if (numIidArray.length % 20 > 0)
				{
					++pages;
				}
				_log.info("pages: " + pages);
				for (int i = 0; i < pages; i++)
				{
					int from = i * 20;
					int to = Math.min((i + 1) * 20, numIidArray.length);
					String[] page = Arrays.copyOfRange(numIidArray, from, to);
					if (page != null && page.length > 0)
					{
						String partialNumIids = StringUtils.join(page, ",");
						_log.info("page: " + partialNumIids);
						try {
							ItemsListGetResponse rsp = getItems(partialNumIids, fields, session);
							if (rsp.isSuccess())
							{
								List<Item> list = rsp.getItems();
								if (list != null)
								{
									items.addAll(list);
								}
							}
							else
							{
								_log.warning(getError(rsp));
								throw new Exception(rsp.getMsg());
							}
						} catch (ApiException e) {
							_log.log(Level.SEVERE, "", e);
						}
					}
				}
			}
		}
		return items;
	}
	
	public static SellercatsListGetResponse getSellerCategories(String nick) throws ApiException
	{
		SellercatsListGetRequest req = new SellercatsListGetRequest();
		req.setNick(nick);
		SellercatsListGetResponse rsp = createClient().execute(req);
		return rsp;
	}
	
	public static String getUserInfo(String nick) throws ApiException
	{
		TaobaoClient client = new DefaultTaobaoClient(getApiUrl(), getAppKey(), getAppSecret());
		UserGetRequest req = new UserGetRequest();
		req.setNick(nick);
		req.setFields("alipay_account");
		 
		UserGetResponse rsp = client.execute(req);
		return rsp.getBody();
	}
	
	public static List<ArticleUserSubscribe> getSubscription(String nick, String articleCode) throws ApiException
	{
		TaobaoClient client = new DefaultTaobaoClient(getApiUrl(), getAppKey(), getAppSecret());
		VasSubscribeGetRequest req = new VasSubscribeGetRequest();
		req.setNick(nick);
		req.setArticleCode(articleCode);
		 
		VasSubscribeGetResponse rsp = client.execute(req);
		return rsp.getArticleUserSubscribes();
	}
	
	public static boolean verifyVersion(String appKey, String leaseId, String timestamp, String versionNo, String sign, String appSecret)
    {
		StringBuilder result = new StringBuilder();
		result.append("appkey").append(appKey)
		.append("leaseId").append(leaseId);
		if (timestamp != null)
		{
			result.append("timestamp").append(timestamp);
		}
		result.append("versionNo").append(versionNo);
		result.insert(0, appSecret);
		result.append(appSecret);
		_log.info("sign: " + sign);
		String s = DigestUtils.md5Hex(result.toString());
		_log.info("s: " + s);
		return sign != null && sign.equals(s.toUpperCase());
    }
	
	public static boolean verifySubscription(String nick, String itemCode)
    {
		try {
			List<ArticleUserSubscribe> subscriptions = getSubscription(nick, ARTICLE_CODE);
			if (subscriptions != null)
			{
				for (ArticleUserSubscribe sub : subscriptions)
				{
					if (itemCode.equals(sub.getItemCode()) && new Date().before(sub.getDeadline()))
					{
						return true;
					}
				}
			}
		} catch (ApiException e) {
			_log.log(Level.SEVERE, "", e);
		}
		return false;
    }
	
	public static String getError(TaobaoResponse response)
	{
		return response.getErrorCode() + " - " + response.getMsg() 
			+ " - " + response.getSubCode() + " - " + response.getSubMsg();
	}
	
	public List<Item> getAllOnsaleItems(String fields, String keyword, String sellerCids, String order, String session) throws ApiException
	{
		List<Item> items = new ArrayList<Item>();
		ItemsOnsaleGetResponse rsp = getOnSales(fields, keyword, sellerCids, order, 1, PAGE_SIZE, session);
		if (rsp.isSuccess())
		{
			items.addAll(rsp.getItems());
			long total = rsp.getTotalResults();
			int pageCount = PagingResult.getPageCount(total, PAGE_SIZE);
			for (int i = 2; i <= pageCount; i++)
			{
				rsp = getOnSales(fields, keyword, sellerCids, order, i, PAGE_SIZE, session);
				if (rsp.isSuccess() && rsp.getItems() != null)
				{
					items.addAll(rsp.getItems());
				}
				else
				{
					_log.warning(getError(rsp));
				}
			}
		}
		return items;
	}
	
	public List<Item> getAllInventoryItems(String fields, String keyword, String sellerCids, String order, String session) throws ApiException
	{
		List<Item> items = new ArrayList<Item>();
		ItemsInventoryGetResponse rsp = getInventory(fields, keyword, sellerCids, order, null, 1, PAGE_SIZE, session);
		if (rsp.isSuccess())
		{
			items.addAll(rsp.getItems());
			long total = rsp.getTotalResults();
			int pageCount = PagingResult.getPageCount(total, PAGE_SIZE);
			for (int i = 2; i <= pageCount; i++)
			{
				rsp = getInventory(fields, keyword, sellerCids, order, null, i, PAGE_SIZE, session);
				if (rsp.isSuccess() && rsp.getItems() != null)
				{
					items.addAll(rsp.getItems());
				}
				else
				{
					_log.warning(getError(rsp));
				}
			}
		}
		return items;
	}
	
	public static ItemcatsGetResponse getSubCategories(long parentCid) throws ApiException
	{
		ItemcatsGetRequest req = new ItemcatsGetRequest();
		req.setParentCid(parentCid);
		req.setFields("cid,parent_cid,name");
		return createClient().execute(req);
	}
	
	public static ItemcatsGetResponse getCategory(long cid) throws ApiException
	{
		ItemcatsGetRequest req = new ItemcatsGetRequest();
		req.setCids(String.valueOf(cid));
		req.setFields("cid,parent_cid,name");
		return createClient().execute(req);
	} 
	
	public static ProductGetResponse getProduct(long productId) throws ApiException
	{
		ProductGetRequest req = new ProductGetRequest();
		req.setProductId(productId);
		return createClient().execute(req);
	}
	
	public static List<WeeklyKeyword> getWeeklyKeywords(Item item, int limit, int offset) throws ApiException
	{
		List<String> cnames = new ArrayList<String>();
		long cid = item.getCid();
		while (cid != 0)
		{
			ItemcatsGetResponse rsp = getCategory(cid);
			if (rsp.isSuccess())
			{
				List<ItemCat> cats = rsp.getItemCats();
				ItemCat cat = cats.get(0);
				String cname = cat.getName();
				_log.info("cid: " + cid);
				if (cid != 0)
				{
					cnames.add(cname);
				}
				cid = cat.getParentCid();
			}
			else
			{
				_log.warning(getError(rsp));
			}
		}
		
		Collections.reverse(cnames);
		_log.info("cnames: " + cnames);
		
		String[] cidArray = new String[3];
		cidArray = cnames.toArray(cidArray);
		Connection conn = null;
		try
		{
			conn = DBUtils.getConnection();
			return Dao.INSTANCE.getWeeklyKeywordsByCategories(cidArray, limit, offset, conn);
		}
		catch (Exception e)
		{
			_log.log(Level.SEVERE, "", e);
		}
		finally
		{
			DBUtils.close(conn, null, null);
		}
		return null;
	}
	
	public static List<RealTimeKeyword> getRealTimeKeywords(Item item, int limit, int offset) throws ApiException
	{
		long cid = item.getCid();
		ItemcatsGetResponse rsp = getCategory(cid);
		if (rsp.isSuccess())
		{
			List<ItemCat> cats = rsp.getItemCats();
			ItemCat cat = cats.get(0);
			String cname = cat.getName();
			Connection conn = null;
			try
			{
				conn = DBUtils.getConnection();
				return Dao.INSTANCE.getRealTimeKeywordsByCoreWord(cname, limit, offset, conn);
			}
			catch (Exception e)
			{
				_log.log(Level.SEVERE, "", e);
			}
			finally
			{
				DBUtils.close(conn, null, null);
			}
		}
		else
		{
			_log.warning(getError(rsp));
		}
		return null;
	}
	
	public ItemUpdateResponse updateTitle(long numIid, String title, String session) throws ApiException
	{
		ItemUpdateRequest req = new ItemUpdateRequest();
		req.setNumIid(numIid);
		req.setTitle(title);
		 
		ItemUpdateResponse rsp = createClient().execute(req, session);
		return rsp;
	}
	
	public ItemsGetResponse search(long cid, String fields) throws ApiException
	{
		ItemsGetRequest req = new ItemsGetRequest();
		req.setFields(fields);
		req.setCid(cid);
		req.setPageNo(1L);
		req.setPageSize(10L);
		req.setOrderBy("volume:asc");
		return createClient().execute(req);
	}
	
	public KfcKeywordSearchResponse kfcFilter(String content, String session) throws ApiException
	{
		KfcKeywordSearchRequest req = new KfcKeywordSearchRequest();
		req.setContent(content);
		return createClient().execute(req, session);
	}
	
	public ItempropsGetResponse getBrandsProps(long cid) throws ApiException
	{
		ItempropsGetRequest req=new ItempropsGetRequest();
		req.setFields("name,prop_values");
		req.setCid(cid);
		req.setPid(20000L);//品牌属性ID
		return createClient().execute(req);
	}
	
	public static boolean contains(List<Item> items, Item item)
	{
		if (items != null)
		{
			for (Item item1 : items)
			{
				if (item1.getNumIid().longValue() == item.getNumIid().longValue())
				{
					return true;
				}
			}
		}
		return false;
	}
	
	public static List<Item> removeAll(List<Item> list1, List<Item> list2)
	{
		if (list2 != null)
		{
			Iterator<Item> it = list1.iterator();
			while (it.hasNext())
			{
				Item item = it.next();
				if (contains(list2, item))
				{
					_log.info("exclude item: " + item.getTitle());
					it.remove();
				}
			}
		}
		return list1;
	}
}
